function hookGetStringUTFChars() {
    const symbols = Module.enumerateSymbolsSync("libart.so");
    for (let sym of symbols) {
        if (sym.name.indexOf("CheckJNI") < 0 &&
            sym.name.indexOf("GetStringUTFChars") !== -1) {
            console.log("[*] Found GetStringUTFChars at: " + sym.address + " (" + sym.name + ")");
            Interceptor.attach(sym.address, {
                onEnter: function (args) {
                    this.jstr = args[1];
                    this.isCopy = args[2];

                    console.log("GetStringUTFChars called with:");
                    console.log("  jstr: " + this.jstr);
                    console.log("  isCopy: " + this.isCopy);
                },
                onLeave: function (retval) {
                    if (retval.isNull()) {
                        console.log("  GetStringUTFChars returned NULL");
                    } else {
                        console.log("  C String: " + Memory.readUtf8String(retval));
                    }
                }
            });
            break;
        }
    }
}

function hookNewStringUTF() {
    const symbols = Module.enumerateSymbolsSync("libart.so");
    for (let sym of symbols) {
        if (sym.name.indexOf("CheckJNI") < 0 &&
            sym.name.indexOf("NewStringUTF") !== -1) {
            console.log("[*] Found NewStringUTF at: " + sym.address + " (" + sym.name + ")");
            Interceptor.attach(sym.address, {
                onEnter: function (args) {
                    this.env = args[0];
                    this.cstr = args[1];

                    console.log("NewStringUTF called with:");
                    console.log("  C String: " + Memory.readUtf8String(this.cstr));
                },
                onLeave: function (retval) {
                    console.log("  NewStringUTF returned Java String: " + retval);
                }
            });
            break;
        }
    }
}

setImmediate(function () {
    hookGetStringUTFChars();
    hookNewStringUTF();
});